package com.event.management.frontend.service.impl;

import com.event.management.frontend.domain.Order;
import com.event.management.frontend.domain.Ticket;
import com.event.management.frontend.domain.UserTicket;
import com.event.management.frontend.dto.OrderCreateDTO;
import com.event.management.frontend.dto.OrderDTO;
import com.event.management.frontend.dto.OrderDetailDTO;
import com.event.management.frontend.dto.OrderStatusDTO;
import com.event.management.frontend.dto.UserTicketDTO;
import com.event.management.frontend.mapper.EventMapper;
import com.event.management.frontend.mapper.OrderMapper;
import com.event.management.frontend.mapper.TicketMapper;
import com.event.management.frontend.mapper.UserTicketMapper;
import com.event.management.frontend.service.OrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 订单服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;
    private final TicketMapper ticketMapper;
    private final EventMapper eventMapper;
    private final UserTicketMapper userTicketMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
        @CacheEvict(value = "eventCache", key = "'eventTickets_' + #createDTO.eventId"),
        @CacheEvict(value = "eventCache", key = "'eventDetail_' + #createDTO.eventId")
    })
    public Long createOrder(Long userId, OrderCreateDTO createDTO) {
        if (createDTO.getTickets() == null || createDTO.getTickets().isEmpty()) {
            throw new RuntimeException("至少选择一种票型");
        }
        
        // 目前每个订单只支持一种票型，取第一个票种信息
        OrderCreateDTO.TicketItem ticketItem = createDTO.getTickets().get(0);
        
        // 1. 查询票种信息
        Ticket ticket = ticketMapper.selectById(ticketItem.getTicketId());
        if (ticket == null) {
            throw new RuntimeException("票种不存在");
        }
        
        // 2. 检查库存是否足够
        int stockLeft = ticket.getTotalStock() - ticket.getSoldCount();
        if (stockLeft < ticketItem.getQuantity()) {
            throw new RuntimeException("票种库存不足");
        }
        
        // 3. 创建订单
        Order order = new Order();
        order.setUserId(userId);
        order.setEventId(createDTO.getEventId());
        order.setTicketId(ticketItem.getTicketId());
        order.setQuantity(ticketItem.getQuantity());
        order.setTotalPrice(ticket.getPrice().multiply(new BigDecimal(ticketItem.getQuantity())));
        order.setStatus("unpaid"); // 初始状态为未支付
        order.setRealName(createDTO.getContactName());
        order.setPhone(createDTO.getContactPhone());
        order.setContactEmail(createDTO.getContactEmail());
        order.setAddress(createDTO.getAddress());
        order.setZipCode(createDTO.getZipCode());
        order.setBirthDate(createDTO.getBirthDate());
        order.setCountry(createDTO.getCountry());
        order.setPaymentMethod(createDTO.getPaymentMethod());
        
        // 处理支付详情
        if (createDTO.getPaymentDetails() != null && "creditcard".equals(createDTO.getPaymentMethod())) {
            // 将支付详情转换为JSON字符串保存
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                String paymentDetailsJson = objectMapper.writeValueAsString(createDTO.getPaymentDetails());
                order.setPaymentDetails(paymentDetailsJson);
            } catch (Exception e) {
                log.error("支付详情序列化失败", e);
                throw new RuntimeException("支付详情处理失败");
            }
        }
        
        order.setNote(createDTO.getNote());
        order.setCreatedAt(new Date());
        
        // 4. 保存订单
        orderMapper.insert(order);
        
        log.info("创建订单成功: orderId={}, userId={}, eventId={}", order.getId(), userId, createDTO.getEventId());
        
        // 5. 自动完成支付流程
        autoPayOrder(userId, order.getId());
        
        return order.getId();
    }
    
    /**
     * 自动完成支付流程
     * @param userId 用户ID
     * @param orderId 订单ID
     */
    private void autoPayOrder(Long userId, Long orderId) {
        try {
            // 1. 获取订单
            Order order = orderMapper.selectById(orderId);
            
            // 2. 更新订单状态为已支付
            Date paidTime = new Date();
            orderMapper.updateStatusToPaid(orderId, paidTime);
            
            // 3. 更新票种销量
            Ticket ticket = ticketMapper.selectById(order.getTicketId());
            ticket.setSoldCount(ticket.getSoldCount() + order.getQuantity());
            ticketMapper.updateById(ticket);
            
            // 4. 生成电子票
            List<UserTicket> userTickets = new ArrayList<>();
            for (int i = 0; i < order.getQuantity(); i++) {
                UserTicket userTicket = new UserTicket();
                userTicket.setOrderId(orderId);
                userTicket.setUserId(userId);
                userTicket.setEventId(order.getEventId());
                userTicket.setTicketId(order.getTicketId());
                
                // 生成唯一票码
                String ticketCode = "ETK-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
                userTicket.setTicketCode(ticketCode);
                
                userTicket.setStatus("valid"); // 初始状态为有效
                userTicket.setCreatedAt(new Date());
                
                userTickets.add(userTicket);
            }
            
            // 5. 批量保存电子票
            userTicketMapper.batchInsert(userTickets);
            
            // 6. 增加活动推荐分数
            // 每次购买增加0.5分推荐权重 × 购买数量
            float scoreIncrement = 0.5f * order.getQuantity();
            eventMapper.incrementRecommendScore(order.getEventId(), scoreIncrement);
            
            log.info("订单自动支付成功: orderId={}, userId={}, 生成电子票数量={}, 增加推荐分数={}", 
                orderId, userId, userTickets.size(), scoreIncrement);
        } catch (Exception e) {
            log.error("订单自动支付失败: orderId={}, userId={}, error={}", orderId, userId, e.getMessage());
            throw new RuntimeException("订单自动支付失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
        @CacheEvict(value = "orderCache", key = "'orderDetail_' + #userId + '_' + #orderId"),
        @CacheEvict(value = "orderCache", key = "'orderStatus_' + #orderId")
    })
    public boolean payOrder(Long userId, Long orderId) {
        // 1. 查询订单
        Order order = orderMapper.selectById(orderId);
        if (order == null || !order.getUserId().equals(userId)) {
            throw new RuntimeException("订单不存在或无权操作");
        }
        
        if (!"unpaid".equals(order.getStatus())) {
            throw new RuntimeException("订单状态异常，无法支付");
        }
        
        // 2. 更新订单状态为已支付
        Date paidTime = new Date();
        int rows = orderMapper.updateStatusToPaid(orderId, paidTime);
        if (rows <= 0) {
            throw new RuntimeException("支付失败，请重试");
        }
        
        // 3. 更新票种销量
        Ticket ticket = ticketMapper.selectById(order.getTicketId());
        ticket.setSoldCount(ticket.getSoldCount() + order.getQuantity());
        ticketMapper.updateById(ticket);
        
        // 4. 生成电子票
        List<UserTicket> userTickets = new ArrayList<>();
        for (int i = 0; i < order.getQuantity(); i++) {
            UserTicket userTicket = new UserTicket();
            userTicket.setOrderId(orderId);
            userTicket.setUserId(userId);
            userTicket.setEventId(order.getEventId());
            userTicket.setTicketId(order.getTicketId());
            
            // 生成唯一票码
            String ticketCode = "ETK-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
            userTicket.setTicketCode(ticketCode);
            
            userTicket.setStatus("valid"); // 初始状态为有效
            userTicket.setCreatedAt(new Date());
            
            userTickets.add(userTicket);
        }
        
        // 5. 批量保存电子票
        userTicketMapper.batchInsert(userTickets);
        
        // 6. 增加活动推荐分数
        // 每次购买增加0.5分推荐权重 × 购买数量
        float scoreIncrement = 0.5f * order.getQuantity();
        eventMapper.incrementRecommendScore(order.getEventId(), scoreIncrement);
        
        log.info("订单支付成功: orderId={}, userId={}, 生成电子票数量={}, 增加推荐分数={}", 
            orderId, userId, userTickets.size(), scoreIncrement);
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
        @CacheEvict(value = "orderCache", key = "'orderDetail_' + #userId + '_' + #orderId"),
        @CacheEvict(value = "orderCache", key = "'orderStatus_' + #orderId")
    })
    public boolean cancelOrder(Long userId, Long orderId) {
        // 1. 查询订单
        Order order = orderMapper.selectById(orderId);
        if (order == null || !order.getUserId().equals(userId)) {
            throw new RuntimeException("订单不存在或无权操作");
        }
        
        if (!"unpaid".equals(order.getStatus())) {
            throw new RuntimeException("订单状态异常，无法取消");
        }
        
        // 2. 更新订单状态为已取消
        int rows = orderMapper.updateStatusToCancelled(orderId);
        if (rows <= 0) {
            throw new RuntimeException("取消订单失败，请重试");
        }
        
        log.info("订单取消成功: orderId={}, userId={}", orderId, userId);
        
        return true;
    }

    @Override
    @Cacheable(value = "orderCache", key = "'orderStatus_' + #orderId", unless = "#result == null")
    public OrderStatusDTO getOrderStatus(Long orderId) {
        // 1. 查询订单
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            return null;
        }
        
        OrderStatusDTO statusDTO = new OrderStatusDTO(orderId, order.getStatus());
        
        // 2. 如果订单已支付，则查询电子票信息
        if ("paid".equals(order.getStatus())) {
            List<UserTicket> tickets = userTicketMapper.selectByOrderId(orderId);
            List<UserTicketDTO> ticketDTOs = tickets.stream().map(ticket -> {
                UserTicketDTO dto = UserTicketDTO.builder()
                        .id(ticket.getId())
                        .ticketCode(ticket.getTicketCode())
                        .status("valid".equals(ticket.getStatus()) ? 0 : 
                               "used".equals(ticket.getStatus()) ? 1 : 3)
                        .build();
                return dto;
            }).collect(Collectors.toList());
            
            statusDTO.setTickets(ticketDTOs);
        }
        
        return statusDTO;
    }

    @Override
    //@Cacheable(value = "orderCache", key = "'orderDetail_' + #userId + '_' + #orderId", unless = "#result == null")
    public OrderDetailDTO getOrderDetail(Long userId, Long orderId) {
        // 1. 查询订单
        Order order = orderMapper.selectById(orderId);
        if (order == null || !order.getUserId().equals(userId)) {
            return null;
        }
        
        // Debug logging to see what's in the order
        log.info("获取订单详情 - 联系人信息: orderId={}, contactEmail={}, birthDate={}, country={}", 
            orderId, order.getContactEmail(), order.getBirthDate(), order.getCountry());
        
        // 2. 查询活动信息
        com.event.management.frontend.domain.Event event = eventMapper.selectById(order.getEventId());
        
        // 3. 查询票种信息
        Ticket ticket = ticketMapper.selectById(order.getTicketId());
        
        // 4. 组装订单详情
        OrderDetailDTO detailDTO = new OrderDetailDTO();
        BeanUtils.copyProperties(order, detailDTO);
        
        // 显式设置联系人信息字段，确保不会丢失
        detailDTO.setContactEmail(order.getContactEmail());
        detailDTO.setBirthDate(order.getBirthDate());
        detailDTO.setCountry(order.getCountry());
        
        // 设置活动信息
        detailDTO.setEventName(event.getTitle());
        detailDTO.setEventStartTime(java.util.Date.from(event.getStartTime().atZone(java.time.ZoneId.systemDefault()).toInstant()));
        detailDTO.setEventLocation(event.getLocation());
        
        // 设置票种信息
        detailDTO.setTicketName(ticket.getName());
        detailDTO.setTicketPrice(ticket.getPrice());
        
        // 设置状态描述
        detailDTO.setStatusDesc(getStatusDesc(order.getStatus()));
        
        // Debug logging to see what's in the DTO
        log.info("获取订单详情 - DTO联系人信息: orderId={}, contactEmail={}, birthDate={}, country={}", 
            orderId, detailDTO.getContactEmail(), detailDTO.getBirthDate(), detailDTO.getCountry());
        
        // 5. 如果订单已支付，则查询电子票信息
        if ("paid".equals(order.getStatus())) {
            List<UserTicket> tickets = userTicketMapper.selectByOrderId(orderId);
            List<UserTicketDTO> ticketDTOs = tickets.stream().map(t -> {
                UserTicketDTO dto = UserTicketDTO.builder()
                        .id(t.getId())
                        .orderId(t.getOrderId())
                        .eventId(t.getEventId())
                        .eventName(event.getTitle())
                        .ticketTypeId(t.getTicketId())
                        .ticketTypeName(ticket.getName())
                        .ticketCode(t.getTicketCode())
                        .price(ticket.getPrice().multiply(new BigDecimal("100")).intValue())
                        .eventStartTime(event.getStartTime())
                        .eventEndTime(event.getEndTime())
                        .eventVenue(event.getLocation())
                        .status("valid".equals(t.getStatus()) ? 0 : 
                                "used".equals(t.getStatus()) ? 1 : 3)
                        .createTime(t.getCreatedAt().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime())
                        .build();
                return dto;
            }).collect(Collectors.toList());
            
            detailDTO.setTickets(ticketDTOs);
        }
        
        return detailDTO;
    }

    @Override
    @Cacheable(value = "orderCache", key = "'myOrders_' + #userId + '_' + #page + '_' + #size", unless = "#result == null || #result.isEmpty()")
    public List<OrderDTO> getMyOrders(Long userId, int page, int size) {
        // 计算偏移量
        int offset = (page - 1) * size;
        
        // 查询用户订单列表
        List<Order> orders = orderMapper.selectByUserIdWithPage(userId, offset, size);
        
        // 转换为DTO
        return orders.stream().map(order -> {
            OrderDTO dto = new OrderDTO();
            BeanUtils.copyProperties(order, dto);
            
            // 查询活动和票种信息
            com.event.management.frontend.domain.Event event = eventMapper.selectById(order.getEventId());
            Ticket ticket = ticketMapper.selectById(order.getTicketId());
            
            dto.setEventName(event.getTitle());
            dto.setTicketName(ticket.getName());
            dto.setStatusDesc(getStatusDesc(order.getStatus()));
            
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "orderCache", key = "'countMyOrders_' + #userId", unless = "#result == 0")
    public long countMyOrders(Long userId) {
        return orderMapper.countByUserId(userId);
    }

    @Override
    @Cacheable(value = "orderCache", key = "'filteredOrders_' + #userId + '_' + #page + '_' + #size + '_' + #keyword + '_' + #status", unless = "#result == null || #result.isEmpty()")
    public List<OrderDTO> getFilteredOrders(Long userId, int page, int size, String keyword, String status) {
        // 计算偏移量
        int offset = (page - 1) * size;
        
        // 查询用户订单列表
        List<Order> orders = orderMapper.selectFilteredOrders(userId, offset, size, keyword, status);
        
        // 转换为DTO
        return orders.stream().map(order -> {
            OrderDTO dto = new OrderDTO();
            BeanUtils.copyProperties(order, dto);
            
            // 查询活动和票种信息
            com.event.management.frontend.domain.Event event = eventMapper.selectById(order.getEventId());
            Ticket ticket = ticketMapper.selectById(order.getTicketId());
            
            // 添加非空检查，避免空指针异常
            if (event != null) {
                dto.setEventName(event.getTitle());
            } else {
                dto.setEventName("未知活动");
                log.warn("订单关联的活动不存在，订单ID: {}, 活动ID: {}", order.getId(), order.getEventId());
            }
            
            if (ticket != null) {
                dto.setTicketName(ticket.getName());
            } else {
                dto.setTicketName("未知票种");
                log.warn("订单关联的票种不存在，订单ID: {}, 票种ID: {}", order.getId(), order.getTicketId());
            }
            
            dto.setStatusDesc(getStatusDesc(order.getStatus()));
            
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "orderCache", key = "'countFilteredOrders_' + #userId + '_' + #keyword + '_' + #status", unless = "#result == 0")
    public long countFilteredOrders(Long userId, String keyword, String status) {
        return orderMapper.countFilteredOrders(userId, keyword, status);
    }
    
    /**
     * 获取状态描述
     */
    private String getStatusDesc(String status) {
        switch (status) {
            case "unpaid":
                return "待支付";
            case "paid":
                return "已支付";
            case "cancelled":
                return "已取消";
            default:
                return "未知状态";
        }
    }
} 